﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ComponentFactory.Krypton.Toolkit;

namespace FastFood.Windows.Controles
{
    #region Enumeracion

    /// <summary>
    /// Enum of Data Type
    /// </summary>
    public enum DataType
    {
        /// <summary>
        /// Represents to Alfanumerico
        /// </summary>
        Alfanumerico,

        /// <summary>
        /// Represents to Enteros
        /// </summary>
        Enteros,

        /// <summary>
        /// Represents to Decimales
        /// </summary>
        Decimales,

        /// <summary>
        /// Represents to Solo Texto
        /// </summary>
        SoloTexto,

        /// <summary>
        /// Represents to Default
        /// </summary>
        Default
    }

    #endregion

    public partial class CustomKryptonTextBox : KryptonTextBox
    {
        #region Atributos

        /// <summary>
        /// Atributo para MaxValue
        /// </summary>
        private int maxValue = 0;

        /// <summary>
        /// Attributo para Mayusculas
        /// </summary>
        private bool isUppercase = false;

        /// <summary>
        /// Atributo para NumeroDecimales
        /// </summary>
        private int numberDecimals = 3;

        /// <summary>
        /// Atributo para BackColorEnter
        /// </summary>
        private Color backColorEnter = SystemColors.Window;

        /// <summary>
        /// Atributo para ForeColorEnter
        /// </summary>
        private Color foreColorEnter = SystemColors.WindowText;

        /// <summary>
        /// Atributo para BackColorLeave
        /// </summary>
        private Color backColorLeave = SystemColors.Window;

        /// <summary>
        /// Atributo para ForeColorLeave
        /// </summary>
        private Color foreColorLeave = SystemColors.WindowText;

        /// <summary>
        /// Atributo para Enum DataType
        /// </summary>
        private DataType dataType = DataType.Alfanumerico;

        #endregion

        #region Metodos Base

        /// <summary>
        /// Initializes a new instance of the CustomTextBox class.
        /// </summary>
        public CustomKryptonTextBox()
        {
            InitializeComponent();
        }

        #endregion

        #region Propiedades

        /// <summary>
        /// Gets or sets the Max value
        /// </summary>
        [Category("Personalizar"), Description("Establece el valor maximo que podrá aceptar los Enteros")]
        public int MaxValue
        {
            get { return this.maxValue; }
            set { this.maxValue = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the text Is Mayusculas
        /// </summary>
        [Category("Personalizar"), Description("Indica si se desea convertir a mayuscula el texto ingresado")]
        public bool IsMayusculas
        {
            get { return this.isUppercase; }
            set { this.isUppercase = value; }
        }

        /// <summary>
        /// Gets or sets the Number of Decimals
        /// </summary>
        [Category("Personalizar"), Description("Establece el numero de decimales permitidos")]
        public virtual int NumberDecimals
        {
            get { return this.numberDecimals; }
            set { this.numberDecimals = value; }
        }

        /// <summary>
        /// Gets or sets the Back Color Enter
        /// </summary>
        [Category("Personalizar"), Description("Estable el color de fondo cuando el control obtiene el foco")]
        public virtual Color BackColorEnter
        {
            get { return this.backColorEnter; }
            set { this.backColorEnter = value; }
        }

        /// <summary>
        /// Gets or sets the Fore Color Enter
        /// </summary>
        [Category("Personalizar"), Description("Establece el color de letra cuando el control obtiene el foco")]
        public virtual Color ForeColorEnter
        {
            get { return this.foreColorEnter; }
            set { this.foreColorEnter = value; }
        }

        /// <summary>
        /// Gets or sets the Back Color Leave
        /// </summary>
        [Category("Personalizar"), Description("Estable el color de fondo cuando el control pierde el foco")]
        public virtual Color BackColorLeave
        {
            get { return this.backColorLeave; }
            set { this.backColorLeave = value; }
        }

        /// <summary>
        /// Gets or sets the Fore COlor Leave
        /// </summary>
        [Category("Personalizar"), Description("Establece el color de letra cuando el control pierde el foco")]
        public virtual Color ForeColorLeave
        {
            get { return this.foreColorLeave; }
            set { this.foreColorLeave = value; }
        }

        /// <summary>
        /// Gets or sets the Data Type
        /// </summary>
        [Category("Personalizar"), Description("Indica el tipo de dato que contendrá el control")]
        public virtual DataType DataType
        {
            get
            {
                return this.dataType;
            }

            set
            {
                this.dataType = value;

                switch (this.dataType)
                {
                    case DataType.Alfanumerico:
                        break;
                    case DataType.Enteros:
                        this.Text = "0";
                        break;
                    case DataType.Decimales:
                        this.Text = "0";
                        break;
                    case DataType.SoloTexto:
                        break;
                    case DataType.Default:
                        break;
                    default:
                        break;
                }
            }
        }

        #endregion

        #region Eventos Base

        /// <summary>
        /// Evento Paint of Control
        /// </summary>
        /// <param name="pe">Información del evento</param>
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
        }

        /// <summary>
        /// Lanzado cuando se Presiona una tecla dentro del control
        /// </summary>
        /// <param name="e">Información del Evento</param>
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            switch (this.dataType)
            {
                case DataType.Decimales:
                    this.DecimalesHandled_KeyPress(this, e);
                    break;
                case DataType.Enteros:
                    this.EnterosHandled_KeyPress(this, e);
                    break;
                case DataType.Alfanumerico:
                    this.AlfanumericoHandled_KeyPress(this, e);
                    break;
                case DataType.SoloTexto:
                    this.SoloTextoHandled_KeyPress(this, e);
                    break;
                case DataType.Default:
                    break;
                default:
                    break;
            }

            base.OnKeyPress(e);
        }

        /// <summary>
        /// Lanzado cuando Obtiene el Foco
        /// </summary>
        /// <param name="e">Información del Evento</param>
        protected override void OnEnter(EventArgs e)
        {
            this.BackColor = this.BackColorEnter;
            this.ForeColor = this.ForeColorEnter;
            base.OnEnter(e);
        }

        /// <summary>
        /// Lanzado cuando pierde el foco
        /// </summary>
        /// <param name="e">Información del Evento</param>
        protected override void OnLeave(EventArgs e)
        {
            this.BackColor = this.BackColorLeave;
            this.ForeColor = this.ForeColorLeave;
            base.OnLeave(e);
        }

        #endregion

        #region Validaciones

        /// <summary>
        /// Lanzado cuando se presiona una tecla dentro del control
        /// Valida que solo ingrese numeros decimales
        /// </summary>
        /// <param name="sender">Control TextBox</param>
        /// <param name="e">Información del Evento</param>
        private void DecimalesHandled_KeyPress(object sender, KeyPressEventArgs e)
        {
            int decimales = 0;
            bool isValid = e.KeyChar == '0' || e.KeyChar == '1' || e.KeyChar == '2' || e.KeyChar == '3' ||
                e.KeyChar == '4' || e.KeyChar == '5' || e.KeyChar == '6' || e.KeyChar == '7' || e.KeyChar == '8' ||
                e.KeyChar == '9' || e.KeyChar == Convert.ToChar(Keys.Back) || e.KeyChar == '.';

            if (this.Text.Contains("."))
            {
                decimales = this.CantidadDecimales(this.Text);
            }

            if ((this.Text.Contains(".") && e.KeyChar == '.') || (decimales >= this.NumberDecimals && e.KeyChar != (char)Keys.Back))
            {
                e.Handled = true;
            }
            else
            {
                e.Handled = !isValid;
            }
        }

        /// <summary>
        /// Lanzado cuando se presiona una tecla dentro del control
        /// Valida que solo ingrese numeros enteros
        /// </summary>
        /// <param name="decimalTextBox">Control TextBox</param>
        /// <param name="e">Información del Evento</param>
        private void EnterosHandled_KeyPress(CustomKryptonTextBox decimalTextBox, KeyPressEventArgs e)
        {
            int valor = 0;
            float posibleValor = 0;
            if (int.TryParse(this.Text, out valor))
            {
                valor = int.Parse(this.Text);
            }

            if (float.TryParse(e.KeyChar.ToString(), out posibleValor))
            {
                posibleValor = float.Parse(valor.ToString() + e.KeyChar.ToString());
            }

            if (this.MaxValue != 0)
            {
                if (((e.KeyChar >= '0' && e.KeyChar <= '9') && (posibleValor <= this.MaxValue)) || e.KeyChar == (char)Keys.Back)
                {
                    e.Handled = false;
                }
                else
                {
                    e.Handled = true;
                }
            }
            else
            {
                if ((e.KeyChar >= '0' && e.KeyChar <= '9') || e.KeyChar == (char)Keys.Back)
                {
                    e.Handled = false;
                }
                else
                {
                    e.Handled = true;
                }
            }
        }

        /// <summary>
        /// Lanzado cuando se presiona una tecla dentro del control
        /// Valida que solo ingrese texto alfanumerico
        /// </summary>
        /// <param name="sender">Control TextBox</param>
        /// <param name="e">Información del Evento</param>
        private void AlfanumericoHandled_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (this.IsMayusculas)
            {
                e.KeyChar = char.ToUpper(e.KeyChar);
            }

            if ((e.KeyChar >= '0' && e.KeyChar <= '9') || (e.KeyChar >= 'a' && e.KeyChar <= 'z') || (e.KeyChar >= 'A' && e.KeyChar <= 'Z') || e.KeyChar == (char)Keys.Back || Char.IsWhiteSpace(e.KeyChar) || e.KeyChar == 'ñ' || e.KeyChar == 'Ñ')
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }

        /// <summary>
        /// Lanzado cuando se presiona una tecla dentro del control
        /// Valida que solo se ingrese Texto
        /// </summary>
        /// <param name="decimalTextBox">Control TextBox</param>
        /// <param name="e">Información del Evento</param>
        private void SoloTextoHandled_KeyPress(CustomKryptonTextBox decimalTextBox, KeyPressEventArgs e)
        {
            if (this.IsMayusculas)
            {
                e.KeyChar = char.ToUpper(e.KeyChar);
            }

            if ((e.KeyChar >= 'a' && e.KeyChar <= 'z') || (e.KeyChar >= 'A' && e.KeyChar <= 'Z') || e.KeyChar == (char)Keys.Back || Char.IsWhiteSpace(e.KeyChar) || e.KeyChar == 'ñ' || e.KeyChar == 'Ñ')
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }

        #endregion

        #region Funciones

        /// <summary>
        /// Retorna cantidad de decimales ingresados
        /// </summary>
        /// <param name="numero">numero ingresado</param>
        /// <returns>cantidad decimales</returns>
        private int CantidadDecimales(string numero)
        {
            string[] partes = numero.ToString().Split('.');

            if (partes[1] != null)
            {
                return partes[1].Length;
            }
            else
            {
                return 0;
            }
        }

        #endregion
    }
}
